home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / gcl-1.000 / gcl-1 / gcl-1.0 / c / run_process.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-25  |  7.0 KB  |  331 lines

  1. /* By Mike Ballantyne */
  2.  
  3.  
  4. #define IN_RUN_PROCESS
  5. #include "include.h"
  6. #ifdef RUN_PROCESS
  7.  
  8. /*
  9.  * System Include Files
  10.  *
  11.  * The system files here each define some part of the information needed to
  12.  * compile the inet package.  They need to exist of every host you port this
  13.  * code to.  I have added some comments that I hope will help you "find"
  14.  * the file if it does not have the same name of your host.
  15.  */
  16. #undef PAGESIZE
  17. #include <errno.h>    /* errno global, error codes for UNIX IO    */
  18. #include <sys/types.h>    /* Data types definitions            */
  19. #include <sys/socket.h>    /* Socket definitions with out this forget it    */
  20. #include <netinet/in.h>    /* Internet address definition AF_INET etc...    */
  21. #include <signal.h>    /* UNIX Signal codes                */
  22. #include <sys/ioctl.h>    /* IO control standard UNIx fair        */
  23. #include <sys/file.h>
  24. #include <fcntl.h>    /* Function to set socket aync/interrupt    */
  25. #include <sys/time.h>    /* Time for select time out                     */
  26. #include <netdb.h>    /* Data Base interface for network files    */
  27. #include <stdio.h>
  28.  
  29.  
  30.  
  31. /* LISP - Lisp Wrapper for the "c" code.
  32.  *
  33.  * The lisp OBJECT is passed to the code and a string must be extracted
  34.  * and null terminated to make it work with the "C" code.
  35.  *
  36.  * Lisp Interface code.
  37.  */
  38.  
  39. static char *lisp_to_string(string)
  40. object string;
  41. {
  42.     int    i, len;
  43.     char    *sself;
  44.     char    *cstr;
  45.  
  46.     len = string->st.st_fillp;
  47.  
  48.     cstr = (char *) malloc (len+1);
  49.     sself = &(string->st.st_self[0]);
  50.     for (i=0; i<len; i++)
  51.     {
  52.         cstr[i] = sself[i];
  53.     }
  54.     cstr[i] = 0;
  55.     return (cstr);
  56. }
  57.  
  58. /* open_connection - Open_Connection a socket to a server that you know by port number.
  59.  *
  60.  * The caller must know the number of the service and and name of the
  61.  * host that tyhe serive is on.  The name of the host can be "localhost"
  62.  * for a service on the same host as the clinet.
  63.  *
  64.  */
  65. static int open_connection(host,server)
  66. char    *host;
  67. int    server;
  68. {
  69.     int res;
  70.     int pid;
  71.     int    sock;
  72.     struct    hostent    *hp;
  73.     struct    sockaddr_in    sock_add;    /* Address of socket          */
  74.  
  75.     if((hp = gethostbyname(host)) == NULL)
  76.     {
  77.         FEerror("No such host.");
  78.     }
  79.  
  80.     bzero((char *)&sock_add, sizeof(sock_add));
  81.     bcopy(hp->h_addr, (char *)&sock_add.sin_addr, hp->h_length);
  82.     sock_add.sin_family = hp->h_addrtype;
  83.     sock_add.sin_port = server;
  84.  
  85.     sock = socket( hp->h_addrtype, SOCK_STREAM , 0);
  86.  
  87.     if(sock < 1)
  88.     {
  89.         FEerror("No Sockets!");
  90.     }
  91.  
  92.     if(connect(sock, (char *)&sock_add, sizeof(sock_add)) < 0)
  93.     {
  94.         close(sock);
  95.         FEerror("Connection Failed.");
  96.     }
  97.     pid = getpid();
  98.     if(ioctl(sock, SIOCSPGRP, (char *)&pid) < 0 )
  99.     {
  100.         FEerror("Could not set process group of socket.");
  101.     }
  102.  
  103. #ifdef OVM_IO
  104.     res = fcntl(sock,F_SETFL,FASYNC | FNDELAY);
  105. #else
  106.     res = fcntl(sock,F_SETFL,FASYNC);
  107. #endif
  108.     return(sock);
  109. }
  110. #define SETBUF(stream) \
  111.     stream->sm.sm_buffer = alloc_contblock(BUFSIZ); \
  112.     setbuf(stream->sm.sm_fp,stream->sm.sm_buffer)
  113.  
  114. object make_stream(host_l,socket,smm)
  115. object    host_l;
  116. int socket;
  117. enum smmode smm;
  118. {
  119.     char    *mode;
  120.     object    stream;
  121.     FILE    *fp;
  122.     vs_mark;
  123.  
  124.  
  125.     switch(smm)
  126.     {
  127.     case smm_input:
  128.         mode = "r";
  129.         break;
  130.     case smm_output:
  131.         mode = "w";
  132.         break;
  133.     default:
  134.         FEerror("make_stream : wrong mode");
  135.     }
  136.  
  137.     fp = fdopen(socket,mode);
  138.     stream = (object)  alloc_object(t_stream);
  139.     stream->sm.sm_mode = (short)smm;
  140.     stream->sm.sm_fp = fp;
  141.  
  142.     stream->sm.sm_object0 = Sstring_char;
  143.     stream->sm.sm_object1 = host_l;
  144.     stream->sm.sm_int0 = stream->sm.sm_int1 = 0;
  145.     vs_push(stream);
  146.     SETBUF(stream)  ;
  147.     vs_reset;
  148.     return(stream);
  149. }
  150.  
  151. object make_socket_stream(host_l,port)
  152. object    host_l;
  153. object    port;
  154. {
  155.     char    *host = lisp_to_string(host_l);
  156.     object    stream_in;
  157.     object    stream_out;
  158.     object    stream;
  159.     int    socket;
  160.  
  161.     socket = open_connection(host, fix(port));
  162.        stream_in  = make_stream(host_l,socket, smm_input);
  163.        stream_out = make_stream(host_l,socket, smm_output);
  164.  
  165.     stream = make_two_way_stream(stream_in,stream_out);
  166.  
  167.     return(stream);
  168. }
  169.  
  170. void
  171. siLmake_socket_stream()
  172. {
  173.   check_arg(2);
  174.   vs_base[0] = make_socket_stream(vs_base[0], vs_base[1]);
  175.   vs_pop;
  176. }
  177.  
  178. /*
  179.  * make 2 two-way streams
  180.  */
  181.  
  182. object
  183. make_socket_pair()
  184. {
  185.   int sockets_in[2];
  186.   int sockets_out[2];
  187.   FILE *fp1, *fp2;
  188.   int pid;
  189.   object stream_in, stream_out, stream;
  190.  
  191.   if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets_in) < 0)
  192.     FEerror("Failure to open socket stream pair", 0);
  193.   if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets_out) < 0)
  194.     FEerror("Failure to open socket stream pair", 0);
  195.   fp1 = fdopen(sockets_in[0], "r");
  196.   fp2 = fdopen(sockets_out[0], "w");
  197.  
  198. #ifdef OVM_IO
  199.   pid = getpid();
  200.   ioctl(sockets_in[0], SIOCSPGRP, (char *)&pid);
  201.   if( fcntl(sockets_in[0], F_SETFL, FASYNC | FNDELAY) == -1)
  202.     perror("Couldn't control socket");
  203.  
  204. #endif
  205.  
  206.  
  207.   stream_in = (object) alloc_object(t_stream);
  208.   stream_in->sm.sm_mode = smm_input;
  209.   stream_in->sm.sm_fp = fp1;
  210.   stream_in->sm.sm_int0 = sockets_in[1];
  211.   stream_in->sm.sm_int1 = 0;
  212.   stream_out = (object) alloc_object(t_stream);
  213.   stream_out->sm.sm_mode = smm_output;
  214.   stream_out->sm.sm_fp = fp2;
  215.   SETBUF(stream_in);
  216.   SETBUF(stream_out);
  217.   stream_out->sm.sm_int0 = sockets_out[1];
  218.   stream_out->sm.sm_int1 = 0;
  219.   stream = make_two_way_stream(stream_in, stream_out);
  220.   return(stream);
  221. }
  222. /* the routines for spawning off a process with streams 
  223.  *
  224.  * Assumes that istream and ostream are both associated
  225.  * with "C" type streams.
  226.  */
  227.  
  228.  
  229. spawn_process_with_streams(istream, ostream, pname, argv)
  230. object istream;
  231. object ostream;
  232. char *pname;
  233. char **argv;
  234. {
  235.  
  236.   int fdin;
  237.   int fdout;
  238.   if (istream->sm.sm_fp == NULL || ostream->sm.sm_fp == NULL)
  239.     FEerror("Cannot spawn process with given stream", 0);
  240.   fdin = istream->sm.sm_int0;
  241.   fdout = ostream->sm.sm_int0;
  242.   if (fork() == 0)
  243.     { /* the child --- replace standard in and out with descriptors given */
  244.       close(0);
  245.       dup(fdin);
  246.       close(1);
  247.       dup(fdout);
  248.       fprintf(stderr, "\n***** Spawning process %s ", pname);
  249.       if (execvp(pname, argv) == -1)
  250.     {
  251.       fprintf(stderr, "\n***** Error in process spawning *******");
  252.       fflush(stderr);
  253.       exit(1);
  254.     }
  255.     }
  256.  
  257.  
  258.  
  259.   
  260. }
  261.     
  262.       
  263. run_process(filename, argv)
  264. char *filename;
  265. char **argv;
  266. {
  267.   object stream = make_socket_pair();
  268.   spawn_process_with_streams(stream->sm.sm_object1,
  269.                 stream->sm.sm_object0,
  270.                 filename, argv);
  271.   vs_base[0] = stream;
  272.   vs_base[1] = Cnil;
  273.   vs_top = vs_base + 2;
  274. }
  275.     
  276. siLrun_process()
  277. {
  278.   int i;
  279.   object arglist;
  280.   char *argv[100];
  281.  
  282.   arglist = vs_base[1];
  283.   argv[0] = "";
  284.   for(i = 1; arglist != Cnil; i++) {
  285.      argv[i] = lisp_to_string(arglist->c.c_car);
  286.      arglist = arglist->c.c_cdr;
  287.   }
  288.   argv[i] = (char *)0;
  289.   run_process(object_to_string(vs_base[0]), argv);
  290. }
  291.  
  292. siLmake_socket_pair()
  293. {
  294.   make_socket_pair();
  295. }
  296.  
  297. init_socket_function()
  298. {
  299.   make_si_function("MAKE-SOCKET-STREAM", siLmake_socket_stream); 
  300.   make_si_function("MAKE-SOCKET-PAIR", siLmake_socket_pair);
  301.   make_si_function("RUN-PROCESS", siLrun_process);
  302. }
  303.  
  304. #ifdef __svr4__
  305. getpagesize()
  306. { return PAGESIZE;
  307. }
  308.  
  309. dlclose()
  310. {fprintf(stderr,"calling 'dl' function sun did not supply..exitting") ;exit(1);}
  311. dgettext()
  312. {dlclose();}
  313. dlopen()
  314. {dlclose();}
  315. dlerror()
  316. {dlclose();}
  317.  
  318. dlsym()
  319. {dlclose();}
  320.  
  321.  
  322.  
  323. #endif
  324.  
  325.  
  326. #else /* no RUN_PROCESS */
  327.  
  328. init_socket_function(){;}
  329.  
  330. #endif     
  331.